package com.redisson.utils;

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;

/**
 * Redisson分布式锁实现-使用可重入非公平锁（RedissonLock）
 */
@Component
public class RedissonDistributedLocker implements DistributedLocker {
    @Autowired
    private RedissonClient redissonClient;

    @Override
    public RLock lock(String lockKey) {
        RLock lock = this.redissonClient.getLock(lockKey);
        lock.lock();
        return lock;
    }

    @Override
    public RLock lock(String lockKey, long timeout) {
        RLock lock = this.redissonClient.getLock(lockKey);
        lock.lock(timeout, TimeUnit.SECONDS);
        return lock;
    }

    @Override
    public RLock lock(String lockKey, TimeUnit unit, long timeout) {
        RLock lock = this.redissonClient.getLock(lockKey);
        lock.lock(timeout, unit);
        return lock;
    }

    @Override
    public boolean tryLock(String lockKey, TimeUnit unit, long leaseTime) {
        RLock lock = this.redissonClient.getLock(lockKey);
        try {
            return lock.tryLock(0L, leaseTime, unit);
        } catch (InterruptedException var7) {
            return false;
        }
    }

    @Override
    public boolean tryLock(String lockKey, TimeUnit unit, long waitTime, long leaseTime) {
        RLock lock = redissonClient.getLock(lockKey);
        try {
            return lock.tryLock(waitTime, leaseTime, unit);
        } catch (InterruptedException e) {
            return false;
        }
    }

    @Override
    public void unlock(String lockKey) {
        RLock lock = redissonClient.getLock(lockKey);
        try {
            if (lock.isLocked()) {
                lock.unlock();
            }
        } catch (IllegalMonitorStateException localIllegalMonitorStateException) {
        }
    }

    @Override
    public void unlock(RLock lock) {
        try {
            if (lock.isLocked()) {
                lock.unlock();
            }
        } catch (IllegalMonitorStateException var3) {
        }
    }


    @Override
    public <T> T tryLockAndRun(String lockKey,TimeUnit unit, long waitTime, long leaseTime,  Supplier<T> supplier, String scene) {

        // 获取分布式锁，最长等待时间:10秒,20秒后自动释放。注意锁与事务的顺序：获取分布式锁 -> 开启事务 -> 执行业务 -> 提交事务 -> 释放分布式锁！！！
        final boolean tryLock = this.tryLock(lockKey, unit, waitTime, leaseTime);

        if (!tryLock) {
            System.out.println("获取分布式锁失败");
        }
        // 注意：一定是获取锁成功后，才进行try{}finally{释放锁}
        try {
            return supplier.get();
        } finally {
            this.unlock(lockKey);
        }
    }

}
